<template>
  <div>
    <div class="shopcart">
      <!-- 购物车内容 -->
      <div class="content">
        <!-- 左半部分 -->
        <div class="content-left" @click="toggleList">
          <div class="logo-wrapper">
            <!-- 购物车图标 -->
            <div class="logo" :class="{ highlight: totalCount > 0 }">
              <i
                class="icon-shopping_cart"
                :class="{ highlight: totalCount > 0 }"
              ></i>
            </div>
            <!-- 购买数量 -->
            <!-- <div class="num" v-show="totalCount > 0"> -->
            <!-- {{ totalCount }} -->
            <bubble
              :num="totalCount"
              v-show="totalCount > 0"
              class="num"
            ></bubble>
            <!-- </div> -->
          </div>
          <!-- 价格 -->
          <div class="price" :class="{ highlight: totalPrice > 0 }">
            ￥{{ totalPrice }}
          </div>
          <!-- 介绍 -->
          <div class="desc">另需配送费￥{{ deliveryPrice }}元</div>
        </div>
        <div class="content-right">
          <!-- 结算价格 -->
          <div class="pay" :class="payClass" @click.stop="pay">
            {{ payDesc }}
          </div>
        </div>
      </div>
    </div>

    <!-- 小球容器 -->
    <div class="ball-container">
      <!-- 遍历小球 -->
      <div v-for="(ball, index) in balls" :key="index">
        <!-- 过度效果 横向和垂直一起移动 -->
        <transition
          @before-enter="beforeDrop"
          @enter="droping"
          @after-enter="afterDrop"
        >
          <div class="ball" v-show="ball.show">
            <div class="inner inner-hook"></div>
          </div>
        </transition>
      </div>
    </div>
  </div>
</template>

<script>
import bubble from "../bubble/bubble.vue";

// 定义小球数组的长度
const BALL_LEN = 10;

// 数组中添加小球，初始不可见
function createBalls() {
  let ret = [];
  for (let i = 0; i < BALL_LEN; i++) {
    ret.push({
      show: false
    });
  }
  return ret;
}
export default {
  components: { bubble },
  name: "shop-cart",
  props: {
    // 已选择的商品
    selectFoods: {
      type: Array,
      default() {
        return [
          {
            price: 10,
            count: 5
          }
        ];
      }
    },
    // 配送费
    deliveryPrice: {
      type: Number,
      default: 0
    },
    // 起送价
    minPrice: {
      type: Number,
      default: 0
    },
    // sticky传递的flod ,不能直接修改，所以传递给this.listFold
    fold: {
      type: Boolean,
      default: true
    },
    // 默认不是复制出来的购物车
    sticky: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      balls: createBalls(),
      // 不需要响应式的，保留就可以
      // dropBalls: [],
      listFold: this.fold
    };
  },
  computed: {
    // 总价
    totalPrice() {
      let price = 0;
      this.selectFoods.forEach(food => {
        price += food.price * food.count;
      });
      return price;
    },
    // 商品数量
    totalCount() {
      let count = 0;
      this.selectFoods.forEach(food => {
        count += food.count;
      });
      return count;
    },
    // 支付描述 根据总价发生变化
    payDesc() {
      if (this.totalPrice === 0) {
        return `￥${this.minPrice}元起送`;
      } else if (this.totalPrice < this.minPrice) {
        const diff = this.minPrice - this.totalPrice;
        return `还差￥${diff}元起送`;
      } else {
        return "去结算";
      }
    },
    // 支付的样式类名
    payClass() {
      // 如果没有买任何商品 或者 价格不够起送价
      if (!this.totalCount || this.totalPrice < this.minPrice) {
        return "not-enough";
      } else {
        return "enough";
      }
    }
  },
  created() {
    // 存放正在下落的小球
    this.dropBalls = [];
    // 购物车列表时候折叠
    // this.listFold = true;
  },
  methods: {
    // 小球掉落 el代表dom元素
    drop(el) {
      // 驱动小球掉落
      for (let i = 0; i < this.balls.length; i++) {
        const ball = this.balls[i];
        // 如果这个球没有显示
        if (!ball.show) {
          // 显示小球
          ball.show = true;
          // 将dom赋值给对应的小球
          ball.el = el;
          // 数组保存下落的小球
          this.dropBalls.push(ball);
          // 返回，保持持续掉落
          return;
        }
      }
    },
    // 支付功能
    pay() {
      // 当总价小于起送费时不能支付
      if (this.totalPrice < this.minPrice) {
        // 直接返回
        return;
      }
      // 掉api弹窗
      this.$createDialog({
        title: "结算",
        content: `需支付${this.totalPrice}元`
      }).show();
    },
    // beforeEnter 进入中
    beforeDrop(el) {
      // 从后向前拿到当前的小球，因为新加的都加在了后面,
      const ball = this.dropBalls[this.dropBalls.length - 1];
      // 获取到按钮的位置
      const rect = ball.el.getBoundingClientRect();
      // 偏移量
      // 水平移动量
      const x = rect.left - 32;
      // 垂直移动量  初始在底部， 将小球移到上面 x为正，y为负值，所以y取反
      const y = -(window.innerHeight - rect.top - 22);
      // 贝塞尔曲线
      el.style.display = "";
      el.style.transform = `translate3d(0, ${y}px, 0)`;
      // 获取内部元素
      const inner = el.getElementsByClassName("inner-hook")[0];
      // x方向偏移
      inner.style.transform = `translate3d(${x}px, 0, 0)`;
    },
    // 在 enter 和 leave 中必须使用 done 进行回调。
    droping(el, done) {
      // 移动到新的位置要触发重绘
      // 重绘
      this._reflow = document.body.offsetHeight;
      // 归位
      el.style.transform = `translate3d(0, 0, 0)`;
      const inner = el.getElementsByClassName("inner-hook")[0];
      inner.style.transform = `translate3d(0, 0, 0)`;

      // 监听事件
      el.addEventListener("transitionend", done);
    },
    // done之后执行
    afterDrop(el) {
      // 下落完成，则在下落小球数组中删除小球，从前向后删除
      const ball = this.dropBalls.shift();
      // 如果删除成功
      if (ball) {
        // 将小球隐藏
        ball.show = false;
        el.style.display = "none";
      }
    },
    // 切换购物车列表
    toggleList() {
      // 如果当前是折叠转态，则显示购物车列表
      if (this.listFold) {
        // 如果总量为0
        if (!this.totalCount) {
          // 不做处理，直接返回
          return;
        }
        // 更改变量
        this.listFold = false;
        // 显示购物车列表
        this._showShopCartList();
        this._showShopCartSticky();
      } else {
        // 更改变量
        this.listFold = true;
        // 隐藏购物车列表
        this._hideShopCartList();
      }
    },
    // 显示列表
    _showShopCartList() {
      // 将实例对象添加到当前实例中
      this.ShopCartListComp =
        this.ShopCartListComp ||
        this.$createShopCartList({
          $props: {
            selectFoods: "selectFoods"
          },
          // 监听事件
          $events: {
            // 触发事件时执行
            hide: () => {
              this.listFold = true;
              // // 这个隐藏是瞬间隐藏，动画不好看
              // this._hideShopCartSticky();
            },
            leave: () => {
              // 这个隐藏是瞬间隐藏，动画不好看
              this._hideShopCartSticky();
            },
            add: el => {
              this.shopCartStickyComp.drop(el);
            }
          }
        });

      // 调用实例方法
      this.ShopCartListComp.show();
    },
    _showShopCartSticky() {
      // 将实例对象添加到当前实例中
      this.shopCartStickyComp =
        this.shopCartStickyComp ||
        this.$createShopCartSticky({
          $props: {
            selectFoods: "selectFoods",
            deliveryPrice: "deliveryPrice",
            minPrice: "minPrice",
            fold: "listFold",
            // 传购物车列表实例
            list: this.ShopCartListComp
          }
        });

      // 调用实例方法
      this.shopCartStickyComp.show();
    },
    // 隐藏列表
    _hideShopCartList() {
      // 判断是否是复制出来的列表
      // this.$parent 就是 sticky 组件
      // list 是购物车列表组件
      const comp = this.sticky ? this.$parent.list : this.ShopCartListComp;
      comp.hide();

      // 调用实例方法
      // this.ShopCartListComp.hide();
    },
    _hideShopCartSticky() {
      // 调用实例方法
      this.shopCartStickyComp.hide();
    }
  },
  watch: {
    // 折叠状态
    fold(newVal, oldVal) {
      this.listFold = newVal;
    },
    totalCount(newVal) {
      // 如果显示商品列表，但是总数量为0在隐藏商品列表
      if (!this.listFold && !newVal) {
        this._hideShopCartList();
      }
    }
  }
};
</script>

<style lang="stylus" scoped>
@import "~common/stylus/variable"

// 购物车定位到页面最下面
.shopcart
  position absolute
  left 0
  bottom 0
  z-index 50
  width: 100%;
  height 48px
  .content
    display flex
    background #141d27
    font-size 0
    color: rgba(255,255,255,0.4)
    .content-left
      flex 1
      // 大圆
      .logo-wrapper
        display inline-block
        vertical-align top
        position relative
        top -10px
        margin 0 12px
        padding 6px
        width 56px
        height 56px
        box-sizing border-box
        border-radius 50%
        background #141d27
        // 小圆
        .logo
          width 100%
          height 100%
          border-radius 50%
          text-align center
          background-color #2b343c
          // 高亮背景色
          &.highlight
            background: $color-blue
          // 购物车图标
          .icon-shopping_cart
            line-height 44px
            font-size 24px
            color: #80858a
            // 高亮
            &.highlight
              color: #fff
        // 商品数量
        .num
          position absolute
          top 0
          right 0
          // width 24px
          // height 16px
          // line-height 16px
          // text-align center
          // border-radius 16px
          // font-size 9px
          // font-weight 700
          // color: #ffffff
          // background-color rgb(240, 20, 20)
          // box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4)
      // 价格
      .price
        display inline-block
        vertical-align top
        margin-top 12px
        line-height 24px
        padding-right 12px
        box-sizing border-box
        border-right: 1px solid rgba(255, 255, 255, 0.1)
        font-size 16px
        font-weight 700
        &.highlight
          color #ffffff
      // 说明
      .desc
        display inline-block
        vertical-align top
        margin 12px 0 0 12px
        line-height 24px
        font-size 10px
    // 右侧结算
    .content-right
      flex 0 0 105px
      width 105px
      .pay
        height 48px
        line-height 48px
        text-align center
        font-size 12px
        font-weight 700
        // 不够起送费
        &.not-enough
          background: #2b333b
        // 够起送费
        &.enough
          background: #00b43c
          color: #fff

.ball-container
  .ball
    position: fixed
    left: 32px
    bottom: 22px
    z-index: 9999
    transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41)
    .inner
      width: 16px
      height: 16px
      border-radius: 50px
      background: $color-blue
      transition: all 0.4s linear
</style>
